package com.example.springboot.config.aop;

import com.example.springboot.config.anotation.repeatsubimit.ExcludeForm;
import com.example.springboot.utils.GetIPUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 定义切面
 *
 * @Author:ChenZhangKun
 * @Date: 2021/5/13 17:26
 */
@Component
@Aspect
@Slf4j
public class ExcludeFormAop {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
/*    // 创建缓存
    private static Set<String> sessions = new HashSet<>();
    // 创建线程池异步执行
    private ExecutorService threadPool = Executors.newFixedThreadPool(5);*/

    /**
     * 切面执行
     *
     * @param joinPoint
     * @param excludeForm
     * @return
     */
    @Around("@annotation(excludeForm)")
    public Object excludeForm(ProceedingJoinPoint joinPoint, ExcludeForm excludeForm) throws Throwable {
/*        // 拿到请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        // 实现自己的逻辑
        HttpSession session = request.getSession();
        //拿到id
        String id = session.getId();
        if (sessions.contains(id)) {
            return "请勿重复提交";
        }
        // 存储
        sessions.add(id);
        System.out.println(id);
        // 拿到请求的时间
        long l = excludeForm.timeOut();
        // 执行
        Object proceed = joinPoint.proceed();
        // 新开线程去定时清除
        threadPool.submit(() -> {
            delete(l, id);
        });
        return proceed;
    }

    private void delete(long l, String id) {
        try {
            Thread.sleep(l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sessions.remove(id);
    }*/
        // 拿到request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 拿到ip
        String ip = GetIPUtils.getIp();
        // 方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 类
        String className = method.getDeclaringClass().getName();
        // 方法名
        String methodName = method.getName();
        String ipKey = String.format("%s#%s", className, methodName);
        // 拿到hash值
        int hashcode = Math.abs(ipKey.hashCode());
        // 拼接redis 的key值
        String key = String.format("%s_%s", ip, hashcode);
        log.info("ipKey={},hashCode={},key={}", ipKey, hashcode, key);
        ExcludeForm annotation = method.getAnnotation(ExcludeForm.class);
        if (annotation != null) {
            long timeOut = annotation.timeOut();
            if (timeOut <= 0) {
                timeOut = 60 * 5 * 1000;
            }
            // 拿到值
            String result = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(result)) {
                return "请勿重复提交";
            }
            redisTemplate.opsForValue().set(key, UUID.randomUUID().toString().replaceAll("-", ""), timeOut, TimeUnit.SECONDS);
            Object proceed = joinPoint.proceed();
            return proceed;
        }
        return joinPoint.proceed();
    }
}
